home *** CD-ROM | disk | FTP | other *** search
File List | 1992-11-21 | 8.5 KB | 329 lines |
- '
- ' Xmdoem/Ymodem CRC/CHK Batch Recieve algorithm
- '
- ' written by Dave Lockwood
- '
- ' It didn't work last time I tested it, and I don't know why...I haven't
- ' taken the time to thoroughly de-bug it, but here it is. If you manage to
- ' make the thing work (especially if you can make it support Ymodem Batch),
- ' PLEASE upload it, and let me know what you did...At the very least, there
- ' are a few usefull routines here for other programs.
- ' In its present state, If it worked, it would support Xmodem w/checksum,
- ' Xmodem CRC, Ymodem w/checksum, and Ymodem CRC.
- ' My goal in this routine was to support the complete Christenson (sp?)
- ' Xmodem standard as defined in his latest papers on the subject.
- '
- ' *** Global definitions and declarations (place at beginning of code)
- '
- Nul%=0 ! block 0 filler byte
- Soh%=1 ! Start Of Header (Xmodem - 128 byte blocks)
- Stx%=2 ! Start Of Header (Ymodem - 1024 byte blocks)
- Eot%=4 ! End Of Transfer
- Ack%=6 ! ACKnolege block
- Nak%=21 ! Not AcKnolege block (block error)
- Can%=24 ! shitCAN transfer (send two of these to abort Ymodem)
- Eof%=26 ! End Of File (CP/M)
- C%=43 ! "C"
- Rs232%=1 ! RS-232 device number for Out statement
- Timeout%=-1 ! timeout value for Inchar routine
- '
- Ymbuf$=String$(1024,Eof%) ! block buffer
- Block0$=String$(128,Nul%) ! block 0 (batch filename) buffer
- '
- ' ****************************** Parity **************************************
- ' calculates parity of a byte
- ' used for Procedure Calcrc below
- ' parameter A% is the byte for which parity is needed
- ' returns Parity% (0=even parity/1=odd parity)
- ' example:
- ' @Parity(Byte%)
- ' If Odd(Parity%)
- ' ...
- Procedure Parity(A%)
- Local Result%,Count%,Q%
- Result%=0
- Count%=8
- While Count%<>0
- Count%=Count%-1
- Q%=A% And 1
- If Q%<>0
- Result%=Result%+1
- Endif
- A%=A%/2
- Wend
- If Odd(Result%)
- Parity%=1
- Else
- Parity%=0
- Endif
- Return
- ' ******************************** CalCrc ************************************
- ' calculates CRC-16 for a single byte at a time
- ' parameter Inbyte% is the byte to add to the CRC
- ' It updates two global variables Crclo% and Crchi%
- ' being the low order and high order 8 bits of the CRC respectively
- ' call this routine for each byte in buffer for which CRC is required
- ' Crclo% and Crchi% should be set to 0 before calling this routine
- ' for the first byte in the buffer.
- ' Translated from Z80 assembly language by Paul Krasno & Dave Lockwood
- Procedure Calcrc(Inbyte%)
- Local A1%,A2%,A3%,A4%,A%,H%,L%
- H%=0
- L%=0
- A1%=Crchi% Xor Inbyte%
- @Parity(A1%)
- If Odd(Parity%)
- H%=3
- L%=&H80
- Endif
- Crcto2:
- A2%=(2*A1%) Mod 256
- A%=A1% And &H80
- If A%<>0
- L%=L% Xor 2
- Endif
- Crcto3:
- A3%=A2% Xor A1%
- A4%=(2*A3%) Mod 256
- A%=A3% And &H80
- If A%<>0
- L%=L% Xor 1
- Endif
- Crcto4:
- Crchi%=Crclo% Xor L%
- Crclo%=A4% Xor H%
- Return
- ' ********************************** Inchar **********************************
- ' waits for a certain amount of time for input
- ' from the RS232 port.
- ' parameter Time% is the time in seconds to wait
- ' returns Char% containing the input or -1 if timeout occurs
- Procedure Inchar(Time%)
- Local Tm%
- Tm%=Timer+Time%*200
- While Timer<>Tm% And Inp?(Rs232%)=False
- Wend
- If Inp?(Rs232%)=True
- Char%=Inp?(Rs232%)
- Else
- Char%=Timeout%
- Endif
- Return
- ' ********************************** Purge ***********************************
- ' clears RS232 input buffer
- ' no parameters/no return
- Procedure Purge
- Char%=1
- While Char%<>Timeout%
- @Inchar(1)
- Wend
- Return
- ' ****************************** Ymodem_recieve ******************************
- '
- ' Ymodem recieve routine
- ' Parameter Path$ is the filename of the input file
- ' returns nothing
- ' doesn't support Ymodem Batch....yet
- '
- Procedure Ymodem_recieve(Path$)
- Local Batch!,Crc!,Icrclo%,Icrchi%,Block%,Bsize%,Fsize%,I%,File$
- Local Iblk%,Iblkcom%,Ercnt%,S%,Cksum%,Icksum%
- Crc!=True
- Batch!=False
- Bsize%=1024
- Block%=1
- Ercnt%=1
- If Path$=""
- Path$="A:\YMODFILE.DAT"
- Endif
- If Right$(Path$,1)<>"\"
- For I%=Len(Path$) To 1 Step -1
- Exit If Mid$(Path$,I%,1)="\"
- Next I%
- File$=Right$(Path$,Len(Path$)-I%)
- Path$=Left$(Path$,I%)
- Else
- File$="YMODFILE.DAT"
- Endif
- If File$="batch"
- File$=""
- Batch!=True
- Endif
- '
- ' open file here...will be moved when I support batch
- ' for batch, a block 0 handling routine must be added
- ' to get each filename to be downloaded
- '
- Open "O",#1,Path$+File$
- '
- Nxtfile:
- Crc!=True
- Bsize%=1024
- Block%=1
- Out 1,C% ! Send a "C" to find out if the sender supports CRC
- Sttran:
- @Inchar(3)
- If Char%=Timeout% ! timeout here means the sender doesn't support CRC
- Crc!=False
- Goto Booboo
- Endif
- Goto Gotsoh
- '
- Startblock:
- '
- Badblock!=False
- @Inchar(1) ! get block number
- If Char%=Timeout%
- Print "Timeout getting block number"
- Badblock!=True
- Goto Booboo
- Endif
- Iblk%=Char%
- '
- @Inchar(1) ! get block number compliment
- If Char%=Timeout%
- Print "Timeout getting block number compliment"
- Badblock!=True
- Goto Booboo
- Endif
- Iblkcom%=Char%
- '
- Gotblknum:
- '
- If Iblk%=(255-Iblkcom%) And Iblk%=0 And Block%=1 ! Block 0 for batch
- ' Batch!=True
- ' @Handle_block0
- Print "Sender wants batch, and I can't do it!!! (I give up)"
- Out Rs232%,Can%
- Out Rs232%,Can%
- Goto Ymrrtn
- Endif
- '
- If Iblk%<>(Block% And 255) Or Iblkcom%<>(255-(Block% And 255))
- Print "Bad block number ";Iblk%,255-Iblkcom%
- Badblock!=True
- Goto Booboo
- Endif
- '
- Print "Getting block ";Block%;" try number ";Ercnt%
- Badblock!=False
- Crclo%=0
- Crchi%=0
- '
- For I%=1 To Bsize% ! get the "meat" of the block
- @Inchar(1)
- If Char%=Timeout%
- Print "Timeout during data block"
- Badblock!=True
- Endif
- Exit If Badblock!=True
- Mid$(Ymbuf$,I%,1)=Chr$(Char%) ! store each byte in buffer
- If Crc!=True
- @Calcrc(Char%) ! calculate CRC
- Else
- Cksum%=Cksum%+Char% ! add to sum
- Endif
- Next I%
- '
- If Badblock!=True
- Goto Booboo
- Endif
- '
- @Inchar(1) ! get CRC hi byte
- If Char%=Timeout%
- Print "Timeout getting CRC lo byte"
- Badblock!=True
- Goto Booboo
- Endif
- '
- If Crc!=False ! if not in CRC mode,
- Icksum%=Char% ! that's our checksum
- Goto Check_sum
- Endif
- '
- Icrchi%=Char%
- @Inchar(1) ! get CRC lo byte
- If Char%=Timeout%
- Print "Timeout getting CRC hi byte"
- Badblock!=True
- Goto Booboo
- Endif
- Icrclo%=Char%
- '
- If Icrclo%<>Crclo% Or Icrchi%<>Crchi% ! compare CRC's
- Print "CRC mismatch - mine:";Crchi%*256+Crclo%;", his:";Icrchi%*256+Icrclo%
- Badblock!=True
- Goto Booboo
- Endif
- '
- Block_ok:
- '
- Out 1,Ack% ! send ACK
- '
- Awaitsoh:
- '
- @Inchar(10) ! wait for SOH or STX
- '
- Gotsoh:
- '
- If Char%=Timeout%
- Badblock!=True
- Goto Booboo
- Endif
- '
- If Char%<>Soh% And Char%<>Stx% And Char%<>Eot% ! wrong char (sync error)
- Print "Sync error"
- Badblock!=True
- Goto Booboo
- Endif
- '
- S%=Bsize%
- If Char%=Soh% ! SOH means set block size to 128 bytes (Xmodem)
- Bsize%=128
- Endif
- If Char%=Stx% ! STX means set block size to 1024 bytes (Ymodem)
- Bsize%=1024
- Endif
- '
- Bput #1,Varptr(Ymbuf$),S% ! save after each block (slow, but it works)
- '
- If Char%=Eot% ! at end of transfer, close file, and quit
- Close #1
- Out 1,Ack% ! don't forget to ACK the EOT
- '
- ' Patch goto till I support Ymodem Batch
- ' otherwise, I'd return to the beginning and get another block 0
- ' (Goto Nxtfile)
- '
- Goto Ymrrtn
- Goto Nxtfile
- Endif
- Inc Block%
- Goto Startblock
- '
- Booboo:
- '
- @Purge ! clear out RS-232 buffer
- Out 1,Nak% ! send NAK
- Inc Ercnt% ! increment error count
- If Ercnt%=11
- Print "Too many errors...aborting download!"
- Out Rs232%,Can%
- Out Rs232%,Can%
- Close #1
- Goto Ymrrtn
- Endif
- Goto Awaitsoh ! wait for SOH/STX of retry
- '
- Check_sum:
- '
- Cksum%=Cksum% And 255 ! only 8 bits of the checksum are used
- If Cksum%<>Icksum%
- Print "Checksum error"
- Goto Booboo
- Endif
- Goto Block_ok
- '
- Ymrrtn:
- Return
-